(function($, undefined) {
	var last_active, start_x_pos, start_y_pos, click_dragged,
		base_classes = 'mkui-button mkui-widget mkui-state-default mkui-corner-all',
		state_classes = 'mkui-state-hover mkui-state-active',
		type_classes = 'mkui-button-icons-only mkui-button-icon-only mkui-button-text-icons mkui-button-text-icon-primary mkui-button-text-icon-secondary mkui-button-text-only',
		form_reset_handler = function() {
			var buttons = $(this).find(':mkui-button');
			setTimeout(function() {
				buttons.button('refresh');
			}, 1);
		},
		radio_group = function(radio) {
			var name = radio.name,
				form = radio.form,
				radios = $([]);
				
			if (name) {
				if (form) {
					radios = $(form).find('[name="' + name + '"]');
				} else {
					radios = $('[name="' + name + '"]', radio.ownerDocument)
							.filter(function() {
								return !this.form;
							});
				}
			}
			return radios;
		};
	
	$.widget('mkui.button', {
		options: {
			disabled: null,
			text: true,
			label: null,
			icons: {
				primary: null,
				secondary: null
			}
		},
		__create: function() {
			// 从元素本身开始，逐级向上级元素匹配，并返回最先匹配的元素。
			this.element.closest('form')
				.unbind('reset.button')
				.bind('reset.button', form_reset_handler);
			if (typeof this.options.disabled !== 'boolean') {
				this.options.disabled = !!this.element.prop_attr('disabled');
			} else {
				this.element.prop_attr('disabled', this.options.disabled);
			}
			
			this.__determine_button_type();
			this.has_title = !!this.button_element.attr('title');
			
			var self = this,
				options = this.options,
				toggle_button = this.type === 'checkbox' || this.type === 'radio',
				hover_class = 'mkui-state-hover' + (!toggle_button ? ' mkui-state-active' : ''),
				focus_class = 'mkui-state-focus';			
			
			// 如果参数中，label未设置，则使用按钮控件的html()属性做为label
			if (options.label === null) {
				options.label = this.button_element.html();
			}
			
			this.button_element
				.addClass(base_classes)
				.attr('role', 'button')
				.bind('mouseenter.button', function() {
					if (options.disabled) {
						return ;
					}
					$(this).addClass('mkui-state-hover');
					if (this === last_active) {
						$(this).addClass('mkui-state-active');
					}
				})
				.bind('mouseleave.button', function() {
					if (options.disabled) {
						return ;
					}
					$(this).removeClass(hover_class);
				})
				.bind('click.button', function(event) {
					if (options.disabled) {
						// TODO event.preventDefault()
						event.preventDefault();
						// TODO event.stopImmediatePropagation()
						event.stopImmediatePropagation();
					}
				});
			this.element
				.bind('focus.button', function() {
					self.button_element.addClass(focus_class);
				})
				.bind('blur.button', function() {
					self.button_element.removeClass(focus_class);
				});
			if (toggle_button) {
				this.element.bind('change.button', function() {
					if (click_dragged) {
						return ;
					}
					self.refresh();
				});
				
				this.button_element
					.bind('mousedown.button', function(event) {
						if (options.disabled) {
							return ;
						}
						chlick_dragged = false;
						start_x_pos = event.pageX;
						start_y_pos = event.pageY;
					})
					.bind('mouseup.button', function(event) {
						if (options.disabled) {
							return ;
						}
						if (start_x_pos !== event.pageX || start_y_pos !== event.pageY) {
							click_dragged = true;
						}
					});
			}
			
			// 如果类型是checkbox
			if (this.type === 'checkbox') {
				this.button_element.bind('click.button', function() {
					if (options.disabled || click_dragged) {
						return false;
					}
					$(this).toggleClass('mkui-state-active');
					self.button_element.attr('aria-pressed', self.element[0].checked);
				});
			} else if (this.type === 'radio') {
				this.button_element.bind('click.button', function() {
					if (options.disabled || click_dragged) {
						return false;
					}
					$(this).addClass('mkui-state-active');
					self.button_element.attr('aria-oressed', 'true');
					
					var radio = self.element[0];
					radio_group(radio)
						.not(radio)
						.map(function() {
							return $(this).button('widget')[0];
						})
						.removeClass('mkui-state-active')
						.attr('aria-pressed', 'false');
				});
			} else {
				this.button_element
					// 鼠标按下时，为按钮增加mkui-state-active样式
					.bind('mousedown.button', function() {
						if (options.disabled) {
							return false;
						}
						$(this).addClass('mkui-state-active');
						last_active = this;
						// 为每一个匹配元素的特定事件（像click）绑定一个一次性的事件处理函数。
						$(document).one('mouseup', function() {
							last_active = null;
						});
					})
					// 鼠标抬起时，移除按钮的mkui-state-active样式
					.bind('mouseup.button', function() {
						if (options.disabled) {
							return false;
						}
						$(this).removeClass('mkui-state-active');
					})
					// 键盘按下时，如果按下的是回车或是空格键，则为按钮增加mkui-state-active样式
					.bind('keydown.button', function(event) {
						if (options.disabled) {
							return false;
						}
						if (event.keyCode == $.mkui.keyCode.SPACE || event.keyCode == $.mkui.keyCode.ENTER) {
							$(this).addClass('mkui-state-active');
						}
					})
					// 键盘抬起时，移除按钮的mkui-state-active样式
					.bind('keyup.button', function() {
						$(this).removeClass('mkui-state-active');
					});
				
				// 如果按钮的元素是A标签，且按下的键盘是空格
				// 抬起时，触发A标签的单击事件
				if (this.button_element.is('a')) {
					this.button_element.keyup(function(event) {
						if (event.keyCode === $.mkui.keyCode.SPACE) {
							$(this).click();
						}
					});
				}
			}
			this.__set_option('disabled', options.disabled);
			this.__reset_button();
		},
		__determine_button_type: function() {
			if (this.element.is(':checkbox')) {
				this.type = 'checkbox';
			} else if (this.element.is(':radio')) {
				this.type = 'radio';
			} else if (this.element.is('input')) {
				this.type = 'input';
			} else {
				this.type = 'button';
			}
			
			if (this.type === 'checkbox' || this.type === 'radio') {
				var ancestor = this.element.parents().filter(':last'),
					label_selector = 'label[for="' + this.element.attr('id') + '"]';
				this.button_element = ancestor.find(label_selector);
				if (!this.button_element.length) {
					// siblings() 取得一个包含匹配的元素集合中每一个元素的所有唯一同辈元素的元素集合。可以用可选的表达式进行筛选。
					ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
					this.button_element = ancestor.filter(label_selector);
					if (!this.button_element.length) {
						this.button_element = ancestor.find(label_selector);
					}
				}
				this.element.addClass('mkui-helper-hidden-accessible');
				
				var checked = this.element.is(':checked');
				if (checked) {
					this.button_element.addClass('mkui-state-active');
				}
				this.button_element.attr('aria-pressed', checked);
			} else {
				this.button_element = this.element;
			}
		},
		widget: function() {
			return this.button_element;
		},
		destroy: function() {
			this.element
				.removeClass('mkui-helper-hidden-accessible');
			this.button_element
				.removeClass(base_classes + ' ' + state_classes + ' ' + type_classes)
				.removeAttr('role')
				.removeAttr('aria-pressed')
				.html(this.button_element.find('.mkui-button-text').html());
				
			if (!this.has_title) {
				this.button_element.removeAttr('title');
			}
			
			$.Widget.prototype.destroy.call(this);
		},
		__set_option: function(key, value) {
			$.Widget.prototype.__set_option.apply(this, arguments);
			if (key === 'disabled') {
				if (value) {
					this.element.prop_attr('disabled', true);
				} else {
					this.element.prop_attr('disabled', false);
				}
				return ;
			}
			this.__reset_button();
		},
		refresh: function() {
			// is() 用一个表达式来检查当前选择的元素集合，如果其中至少有一个元素符合这个给定的表达式就返回true。
			var is_disabled = this.element.is(':disabled');
			if (is_disabled !== this.options.disabled) {
				this.__set_option('disabled', is_disabled);
			}
			if (this.type === 'radio') {
				radio_group(this.element[0]).each(function() {
					if ($(this).is(':checked')) {
						$(this).button('widget')
							.addClass('mkui-state-active')
							.attr('aria-pressed', 'true');
					} else {
						$(this).button('widget')
							.removeClass('mkui-state-active')
							.attr('aria-pressed', 'false');
					}
				});
			} else if (this.type === 'checkbox') {
				if (this.element.is(':checked')) {
					this.button_element
						.addClass('mkui-state-active')
						.attr('aria-pressed', 'true');
				} else {
					this.button_element
						.removeClass('mkui-state-active')
						.attr('aria-pressed', 'false');
				}
			}
		},
		__reset_button: function() {
			if (this.type === 'input') {
				if (this.options.label) {
					this.element.val(this.options.label);
				}
				return ;
			}
			var button_element = this.button_element.removeClass(type_classes),
				button_text = $('<span></span>', this.element[0].ownerDocument)
					.addClass('mkui-button-text')
					.html(this.options.label)
					.appendTo(button_element.empty())
					.text(),
				icons = this.options.icons,
				multiple_icons = icons.primary && icons.secondary,
				button_classes = [];
				
			if (icons.primary || icons.secondary) {
				if (this.options.text) {
					button_classes.push('mkui-button-text-icon' + (multiple_icons ? 's' : (icons.primary ? '-primary' : '-secondary')));
				}
				
				if (icons.primary) {
					button_element.prepend('<span class="mkui-button-icon-primary mkui-icon ' + icons.primary + '"></span>');
				}
				
				if (icons.secondary) {
					button_element.append('<span class="mkui-button-icon-secondary mkui-icon ' + icons.secondary + '"></span>')
				}
				
				if (!this.options.text) {
					button_classes.push(multiple_icons ? 'mkui-button-icons-only' : 'mkui-button-icon-only');
					
					if (!this.has_title) {
						button_element.attr('title', button_text);
					}
				}
			} else {
				button_classes.push('mkui-button-text-only');
			}
			button_element.addClass(button_classes.join(' '));
		}
	});
}(jQuery));